﻿using System;
using System.Web.Mvc;
using System.Web.Routing;

using System.Web;
using Infrastructure.Crosscutting.NetFramework.Result;
using System.Reflection;

namespace Infrastructure.Crosscutting.NetFramework.Controllers
{
    public abstract class BaseController : System.Web.Mvc.Controller
    {
        public IWorkContext WorkContext { get; set; }

        public BaseController(IWorkContext work)
        {
            if (work == null)
            {
                throw new ArgumentNullException("WorkContext is null");
            }
            WorkContext = work;
        }

        #region overriide method

        protected override void Initialize(System.Web.Routing.RequestContext requestContext)
        {
            base.Initialize(requestContext);
        }

        protected override JsonResult Json(object data, string contentType, System.Text.Encoding contentEncoding)
        {
            return new CustomJsonResult
            {
                Data = data,
                ContentType = contentType,
                ContentEncoding = contentEncoding
            };
        }

        protected override JsonResult Json(object data, string contentType, System.Text.Encoding contentEncoding, JsonRequestBehavior behavior)
        {
            return new CustomJsonResult
            {
                Data = data,
                ContentType = contentType,
                ContentEncoding = contentEncoding,
                JsonRequestBehavior = behavior
            };
        }

        protected override void OnException(System.Web.Mvc.ExceptionContext filterContext)
        {
            this.AddExceptionLogInfo(filterContext);
            base.OnException(filterContext);
        }

        protected override void OnActionExecuting(System.Web.Mvc.ActionExecutingContext filterContext)
        {
            this.HasPermission(filterContext);
            this.UrlToLower(filterContext);
            var isLog = System.Web.Configuration.WebConfigurationManager.AppSettings["IsStartDbLog"];
            if (!string.IsNullOrEmpty(isLog) && string.Compare(isLog, "true", false) == 0)
            {
                var controllerName = filterContext.ActionDescriptor.ControllerDescriptor.ControllerName.ToLower();
                if (string.Compare(controllerName, "logger", false) != 0)
                {
                    this.AddExcutingLogInfo(filterContext);
                }
            }
            base.OnActionExecuting(filterContext);
        }

        #endregion

        #region util

        protected virtual void HasPermission(System.Web.Mvc.ActionExecutingContext filterContext)
        {
            var isPermission = System.Web.Configuration.WebConfigurationManager.AppSettings["IsStartPermission"];
            if (!string.IsNullOrEmpty(isPermission) && string.Compare(isPermission, "true", false) == 0)
            {
                //用户没有登陆，跳去登陆
                if (this.WorkContext.CurrentUser == null)
                {
                    filterContext.Result = new RedirectResult("/login/");
                }
                else
                {
                    //用户已经登陆了
                    //进行权限的判断
                    var currentController = filterContext.Controller.GetType();
                    var currentAction = filterContext.ActionDescriptor.ActionName;
                    if (!this.WorkContext.HasCurrentPermission(currentController, currentAction))
                    {
                        MethodInfo actionMethod = null;
                        var allMethod = currentController.GetMethods();
                        foreach (var item in allMethod)
                        {
                            if (item.Name.ToLower() == currentAction.ToLower())
                            {
                                actionMethod = item;
                            }
                        }
                        if (actionMethod != null)
                        {
                            if (Infrastructure.Crosscutting.Comm.Service.MvcResultService.IsFileResult(actionMethod))
                            {
                                filterContext.Result = new EmptyResult();
                            }
                            else if (Infrastructure.Crosscutting.Comm.Service.MvcResultService.IsJsonResult(actionMethod))
                            {
                                filterContext.Result = new JsonResult()
                                {
                                    Data = new { total = 0, data = new { Id = "没有权限访问" }, success = false, message = "没有权限访问" }
                                };
                            }
                            else if (Infrastructure.Crosscutting.Comm.Service.MvcResultService.IsOtherResult(actionMethod))
                            {
                                filterContext.Result = filterContext.Result = new EmptyResult();
                            }
                            else if (Infrastructure.Crosscutting.Comm.Service.MvcResultService.IsViewResult(actionMethod))
                            {
                                filterContext.Result = new RedirectResult("/error/denied");
                            }
                            else
                            {
                                filterContext.Result = new RedirectResult("/error/denied");
                            }
                        }
                        else
                        {
                            filterContext.Result = new RedirectResult("/error/denied");
                        }
                    }
                }
            }
        }

        protected virtual void UrlToLower(System.Web.Mvc.ActionExecutingContext filterContext)
        {
            var routes = RouteTable.Routes;
            var context = filterContext.RequestContext;
            var routeData = context.RouteData;
            var dataTokens = routeData.DataTokens;
            if (dataTokens["area"] == null)
                dataTokens.Add("area", "");
            var vpd = routes.GetVirtualPathForArea(context, routeData.Values);
            if (vpd != null)
            {
                var virtualPath = vpd.VirtualPath.ToLower();
                var request = context.HttpContext.Request;
                if (request != null)
                {
                    string path = Request.Path;
                    if (!string.Equals(virtualPath, path))
                    {
                        filterContext.RequestContext.HttpContext.RewritePath("/", virtualPath, request.Url.Query);
                    }
                }
            }
        }

        protected virtual void AddExcutingLogInfo(System.Web.Mvc.ActionExecutingContext filterContext)
        {
            var logType = 1;
            var userId = 0;
            var currentUser = filterContext.HttpContext.Session[Infrastructure.Crosscutting.Comm
                .Service.ConstService.SessionNameCurrentUser] as Domain.Entity.User;
            if (currentUser != null)
            {
                userId = currentUser.Id;
            }
            var pageUrl = filterContext.HttpContext.Request.Url == null ? string.Empty : filterContext.HttpContext.Request.Url.ToString();
            pageUrl = pageUrl.Length > 500 ? pageUrl.Substring(0, 500) : pageUrl;

            var refUrl = filterContext.HttpContext.Request.UrlReferrer == null ? string.Empty : filterContext.HttpContext.Request.UrlReferrer.ToString();
            refUrl = refUrl.Length > 500 ? refUrl.Substring(0, 500) : refUrl;

            var shortMessage = "1.running controller " + filterContext.Controller.ToString();
            shortMessage += " , 2.running method " + filterContext.ActionDescriptor.ActionName;
            var fullMessage = "1.browser " + filterContext.HttpContext.Request.Browser.Type;
            fullMessage += " , 2.http method " + filterContext.HttpContext.Request.HttpMethod;
            fullMessage += " , 3.total bytes " + filterContext.HttpContext.Request.TotalBytes.ToString();
            fullMessage += " , 4.user host name " + filterContext.HttpContext.Request.UserHostName;
            fullMessage += " , 5.user agent " + filterContext.HttpContext.Request.UserAgent;
            fullMessage += " , 6.user host address " + filterContext.HttpContext.Request.UserHostAddress;
            fullMessage += " , 7.cookies ";
            for (int i = 0; i < filterContext.HttpContext.Request.Cookies.Count; i++)
            {
                var logCookie = filterContext.HttpContext.Request.Cookies.Get(i);
                fullMessage += " cookie name: " + logCookie.Name;
                fullMessage += " ,  cookie value: " + logCookie.Value;
            }
            var ipAddress = Crosscutting.Comm.Service.StringService.GetRealIP();
            Infrastructure.Data.Uow.Log.LoggerRepositoryManager.AddLogInfo(logType, userId, pageUrl, refUrl, shortMessage, fullMessage, ipAddress);
        }

        protected virtual void AddExceptionLogInfo(System.Web.Mvc.ExceptionContext filterContext)
        {
            var logType = 1;
            //如果说是有user的话，应该是在Session里面哦，没有则为0
            var userId = 0;
            var currentUser = filterContext.HttpContext.Session[Infrastructure.Crosscutting.Comm
                .Service.ConstService.SessionNameCurrentUser] as Domain.Entity.User;
            if (currentUser != null)
            {
                userId = currentUser.Id;
            }
            var pageUrl = "";
            var refUrl = "";
            if (filterContext != null && filterContext.HttpContext != null && filterContext.HttpContext.Request != null)
            {
                pageUrl = filterContext.HttpContext.Request.Url == null ? string.Empty : filterContext.HttpContext.Request.Url.ToString();
                refUrl = filterContext.HttpContext.Request.UrlReferrer == null ? string.Empty : filterContext.HttpContext.Request.UrlReferrer.ToString();
            }
            var shortMessage = filterContext.Exception.Message;
            var fullMessage = filterContext.Exception.InnerException == null ? filterContext.Exception.StackTrace : filterContext.Exception.InnerException.Message;
            var ipAddress = Crosscutting.Comm.Service.StringService.GetRealIP();
            Infrastructure.Data.Uow.Log.LoggerRepositoryManager.AddLogInfo(logType, userId, pageUrl, refUrl, shortMessage, fullMessage, ipAddress);
        }

        #endregion
    }
}
